package com.cortex.papaya.search;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.carrot2.core.Document;
import org.carrot2.core.IControllerContext;
import org.carrot2.core.IControllerContextListener;
import org.carrot2.core.ProcessingException;
import org.carrot2.source.MultipageSearchEngine;
import org.carrot2.source.SearchEngineResponse;
import org.carrot2.source.SimpleSearchEngine;
import org.carrot2.source.etools.EToolsDocumentSource;
import org.carrot2.source.google.GoogleDocumentSource;

import com.cortex.papaya.utilities.MyLog;
import com.cortex.papaya.utilities.Utilities;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import android.os.AsyncTask;
import android.util.Log;

/**
 * @author Gal lavie
 * this class is build query to search.
 * MultipageSearchEngine is parameter to select search engine like google or bing and others 
 * 
 *
 */
public class QuerySearch extends SimpleSearchEngine implements IControllerContext,IQuerySearch{

	/**
	 * Google document source, contains bindable attributes.
	 */
	private MultipageSearchEngine searchEngine;
	private String query;
	private SearchEngineResponse response;
	private HashMap<String,Object> map = new HashMap<String,Object>();
	private List<IControllerContextListener> iControllerContextListenerList = new ArrayList<IControllerContextListener>();

	public QuerySearch(MultipageSearchEngine searchEngine, String query) {
		super();
		this.searchEngine = searchEngine;
		this.query = query;
	}
	public MultipageSearchEngine getSearchEngine() {
		return searchEngine;
	}
	public void setSearchEngine(MultipageSearchEngine searchEngine) {
		this.searchEngine = searchEngine;
	}
	@Override
	public String getQuery() {
		return query;
	}
	@Override
	public void setQuery(String query) {
		this.query = query;
	}
	@Override
	public void init(IControllerContext context)
	{
		super.init(context);
		searchEngine.init(context);
	}
	@Override
	public void beforeProcessing() throws ProcessingException {
		searchEngine.beforeProcessing();
	}
	@Override
	public SearchEngineResponse run() throws Exception{
		init(this);
		beforeProcessing();
		fetchSearchResponse();
		afterProcessing();
		return response;
	}
	@Override
	protected SearchEngineResponse fetchSearchResponse() throws Exception {
		try{
			response = new SearchEngineResponse();
			if(query == null || query.isEmpty()){
				throw new Exception("query in empty");
			}

			searchEngine.query = query;
			searchEngine.process();
			Map<String, Document> documentsByUrl = Maps.newHashMap();
			if (searchEngine.documents != null)
			{
				for (Document document : searchEngine.documents){
					documentsByUrl.put((String) document.getField(Document.CONTENT_URL), document);
					// source of document need to change
					document.setField(Document.SOURCES, Lists.newArrayList("Google"));
				}
				response.results.addAll(searchEngine.documents);

			}

			// Trim to size (cannot use sublist because the field is final)
			while (response.results.size() > results){
				response.results.remove(results);
			}

			response.metadata.put(SearchEngineResponse.RESULTS_TOTAL_KEY,searchEngine.resultsTotal);

			return response;
		}
		catch (ProcessingException e) {
			Log.d(MyLog.EXCEPTION_LOG,e.getMessage());
			throw(e);
		} catch(Exception e){
			Log.d(MyLog.EXCEPTION_LOG,e.getMessage());
			throw(e);
		}
	}
	@Override
	public void afterProcessing(){
		searchEngine.afterProcessing();
		searchEngine.documents = null;
	}

	@Override
	public void dispose(){
		searchEngine.dispose();
	}
	@Override
	public void addListener(IControllerContextListener listener) {
		iControllerContextListenerList.add(listener);
	}
	@Override
	public Object getAttribute(String key) {
		return map.get(key);
	}
	@Override
	public void removeListener(IControllerContextListener listener) {
		iControllerContextListenerList.remove(listener);
	}
	@Override
	public void setAttribute(String key, Object value) {
		map.put(key, value);
	}

}
